home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1999 / MacHack 1999.toast / The Hacks / NetPokerForMacOSX_Server / HoldEmHigh / IRCTask.m < prev    next >
Encoding:
Text File  |  1999-06-26  |  12.1 KB  |  450 lines

  1. #import "IRCTask.h"
  2. #import "poker.h"
  3.  
  4. @implementation IRCTask
  5.  
  6. + (id)sharedIRCTask {
  7.    static IRCTask *task = nil;
  8.    if (task == nil) {
  9.     task = [[IRCTask alloc] init];
  10.     }
  11.     return task;
  12. }
  13.  
  14. #define IRC_EXECUTABLE [[NSBundle mainBundle] pathForResource:@"irc" ofType:@""]
  15.  
  16. - (void)pushStringOverWire:(const char *)buf {
  17.     [[to_irc fileHandleForWriting] writeData:[NSData dataWithBytes:buf length:strlen(buf)]];
  18. }
  19.  
  20. - (void)stringToTBot:(const char *)buf {
  21.     [self pushStringOverWire:[[NSString stringWithFormat:@"/msg tbot p %s\n",buf]cString]];
  22. }
  23.  
  24. - (void)returnFromVacation {
  25.     [self stringToTBot:"back"];
  26. }
  27.  
  28. - (void)goOnVacation {
  29.     [self stringToTBot:"vacation"];
  30. }
  31.  
  32. - (void)bet:(int)amount {
  33.     [self stringToTBot:[[NSString stringWithFormat:@"raise %d",amount]cString]];
  34. }
  35.  
  36. - (void)minBet {
  37.     [self stringToTBot:"TODO"];
  38. }
  39.  
  40. - (void)pushAllIn {
  41.     [self stringToTBot:"raise 2000000"];
  42. }
  43.  
  44. - (void)call {
  45.     [self stringToTBot:"call"];
  46. }
  47.  
  48. - (void)fold {
  49.     [self stringToTBot:"fold"];
  50. }
  51.  
  52. - (void)halfPot {
  53.     [self stringToTBot:"TODO"];
  54. }
  55.  
  56. - (int)pot {
  57.     [self stringToTBot:"raise pot"];
  58.     return 0;
  59. }
  60.  
  61. - (void)leaveTable{
  62.     [self stringToTBot:"quit"];
  63. }
  64.  
  65. - (void)joinTable{
  66.     [self pushStringOverWire:"/join #tourney\n"];
  67.     [self stringToTBot:"join i"];
  68. }
  69.  
  70.  
  71. - (Card *)cardFromRankChar:(char)rank_char suitChar:(char)suit_char
  72. {
  73.   const char *suits = "Xcshd";
  74.   const char *ranks = "AKQJT98765432";
  75.   Card *retval;
  76.   Suit s;
  77.   Rank r;
  78.   char *sp;
  79.   char *rp;
  80.  
  81.   s = 0;
  82.   r = 0;
  83.   sp = strchr (suits, suit_char);
  84.   rp = strchr (ranks, rank_char);
  85.   if (sp && rp)
  86.     {
  87.       s = sp - suits;
  88.       r = rp - ranks;
  89.     }
  90.   retval = [Card cardWithSuit:s rank:r];
  91.   return retval;
  92.  
  93. #define TRY_TO_MATCH(sscanf_call, n_expected, method_call) \
  94.   do                                                       \
  95.     if (sscanf sscanf_call == n_expected)                  \
  96.       {                                                    \
  97.         method_call;                                       \
  98.         goto SUCCESS;                                      \
  99.       }                                                    \
  100.   while (FALSE)
  101.  
  102. -(void) addPlayerHelper:(const char *) player cash:(int) amount char1:(char) c1 char2:(char)c2
  103. {
  104.   BOOL is_vaced;
  105.   BOOL is_button;
  106.   Player *p = [pokerTable findPlayerWithName:player];
  107.   [pokerTable addPlayer:player cash:amount];
  108.   is_vaced = c1 == 'V';
  109.   is_button = (c1 == 'B') || (c2 == 'B');
  110.   [p setOnVacation:is_vaced];
  111.   if (is_button) [pokerTable setButtonPlayer:player];
  112.  
  113. }
  114.  
  115. - (BOOL) parseLine:(NSData *)line
  116. {
  117.   char *buf, *orig_buf;
  118.   char *player;
  119.   int n_players;
  120.   BOOL retval;
  121.   int nleft;
  122.   char bang, dot;
  123.   int small_blind;
  124.   int big_blind;
  125.   int blind_remaining;
  126.   char *blind_remaining_units;
  127.   int hand_no;
  128.   int blind;
  129.   int pot;
  130.   int to_call;
  131.   int amount;
  132.   char *by_whom;
  133.   char r1, r2, r3, r4, r5;
  134.   char s1, s2, s3, s4, s5;
  135.   char colon;
  136.   char *hand_string;
  137.   char *message_from;
  138.   volatile BOOL is_public;
  139.  
  140.   buf = alloca ([line length] + 1);
  141.   [line getBytes:buf];
  142.   buf[[line length]] = 0;
  143.   orig_buf = buf;
  144.  
  145.   /* strip portion that shows this coming from TBot */
  146.   if (buf[0] != '<' && buf[0] != '-' && buf[0] != '*')
  147.     return FALSE;
  148.   else
  149.     {
  150.       char desired;
  151.  
  152.       desired = ( buf[0] == '<') ? '>' : buf[0];
  153.       buf = strchr (buf+1, ' ');
  154.       if (!buf || buf[-1] != desired)
  155.     return FALSE;
  156.       else
  157.     {
  158.       int len;
  159.  
  160.           --buf;
  161.       len = buf - orig_buf - 1;
  162.       if (len <= 0)
  163.         return FALSE;
  164.       message_from = alloca (len + 1);
  165.       memcpy (message_from, orig_buf+1, len);
  166.       message_from[len] = 0;
  167.       buf += 2;
  168.       is_public = orig_buf[0] == '<';
  169.     }
  170.     }
  171.  
  172.   player = alloca ([line length] + 1);
  173.   blind_remaining_units = alloca ([line length] + 1);
  174.   by_whom = alloca ([line length] + 1);
  175.   hand_string = alloca ([line length] + 1);
  176.   retval = TRUE;
  177.  
  178.   if (strcmp (message_from, "TBot") != 0) {
  179.         [pokerTable player:message_from messages:buf];
  180.     return TRUE;
  181.   }
  182.  
  183. #if 0
  184.   TRY_TO_MATCH
  185.     (
  186.      (buf, "%s has joined the game.  We now have %d players.", player, &nleft), 2,
  187.      [pokerTable addPlayer:player cash:5000]);
  188. #endif
  189.  
  190.   TRY_TO_MATCH
  191.     (
  192.      (buf, "%s quits.  We now have %d players.", player, &nleft), 2,
  193.      [pokerTable playerQuits:player n_left:nleft]);
  194.  
  195.   TRY_TO_MATCH
  196.     (
  197.      (buf, "Tourney started by %s!", player), 1,
  198.        [pokerTable readyToBeginGame]);
  199.  
  200.   TRY_TO_MATCH
  201.     (
  202.      (buf, "The blinds are currently $%d and $%d.", &small_blind, &big_blind), 2,
  203.      [pokerTable blindsAre:small_blind and:big_blind]);
  204.  
  205.   TRY_TO_MATCH
  206.     (
  207.      (buf, "Blinds will double in %d %s.", &blind_remaining, blind_remaining_units), 2,
  208.      [pokerTable blindsWillDoubleIn:blind_remaining units:blind_remaining_units]);
  209.  
  210.   TRY_TO_MATCH
  211.     (
  212.      (buf, "Game #%d, %d players.  Dealing Holdem high", &hand_no, &n_players), 2,
  213.      [pokerTable beginAddingPlayers]);
  214.  
  215.   TRY_TO_MATCH
  216.     (
  217.      (buf, "%s blinds $%d.  Pot is now $%d.", player, &blind, &pot), 3,
  218.      [pokerTable player:player blinds:blind potNow:pot allIn:NO]);
  219.  
  220.   TRY_TO_MATCH
  221.     (
  222.      (buf, "%s blinds $%d and is all in.  Pot is now $%d.", player, &blind, &pot), 3,
  223.      [pokerTable player:player blinds:blind potNow:pot allIn:YES]);
  224.  
  225.   TRY_TO_MATCH
  226.     (
  227.      (buf, "%s is next to act. (%d to call)", player, &to_call), 2,
  228.      [pokerTable player:player toCall:to_call]);
  229.  
  230.   TRY_TO_MATCH
  231.   (  
  232.    (buf, "%s folds.  We now have %d players in the hand.", player, &n_players), 2,
  233.    [pokerTable player:player foldsLeaving:n_players]);
  234.  
  235.   TRY_TO_MATCH
  236.   (
  237.    (buf, "%s calls $%d.  Pot is now $%d.", player, &amount, &pot), 3,
  238.      [pokerTable player:player calls:amount potNow:pot allIn:NO]);
  239.  
  240.   TRY_TO_MATCH
  241.     (
  242.      (buf, "%s calls $%d and is all in.  Pot is now $%d.", player, &amount, &pot), 3,
  243.      [pokerTable player:player calls:amount potNow:pot allIn:YES]);
  244.  
  245.   TRY_TO_MATCH
  246.     (
  247.      (buf, "%s has sent %s on vacation!", player, by_whom), 2,
  248.      [pokerTable player:player vacationedBy:by_whom]);
  249.  
  250.   TRY_TO_MATCH
  251.     (
  252.      (buf, "%s checks%c", player, &dot), 2,
  253.      [pokerTable playerChecks:player]);
  254.  
  255.   TRY_TO_MATCH
  256.     (
  257.      (buf, "Board:      %c%c %c%c %c%c %c%c %c%c", &r1, &s1, &r2, &s2, &r3, &s3, &r4, &s4, &r5, &s5), 10,
  258.      {[pokerTable publicCardNumber:0 didShowCard:[self cardFromRankChar:r1 suitChar:s1]];
  259.       [pokerTable publicCardNumber:1 didShowCard:[self cardFromRankChar:r2 suitChar:s2]];
  260.       [pokerTable publicCardNumber:2 didShowCard:[self cardFromRankChar:r3 suitChar:s3]];
  261.       [pokerTable publicCardNumber:3 didShowCard:[self cardFromRankChar:r4 suitChar:s4]];
  262.       [pokerTable publicCardNumber:4 didShowCard:[self cardFromRankChar:r5 suitChar:s5]];});
  263.  
  264.   TRY_TO_MATCH
  265.     (
  266.      (buf, "Board:      %c%c %c%c %c%c %c%c", &r1, &s1, &r2, &s2, &r3, &s3, &r4, &s4), 8,
  267.      {[pokerTable publicCardNumber:0 didShowCard:[self cardFromRankChar:r1 suitChar:s1]];
  268.       [pokerTable publicCardNumber:1 didShowCard:[self cardFromRankChar:r2 suitChar:s2]];
  269.       [pokerTable publicCardNumber:2 didShowCard:[self cardFromRankChar:r3 suitChar:s3]];
  270.       [pokerTable publicCardNumber:3 didShowCard:[self cardFromRankChar:r4 suitChar:s4]];});
  271.  
  272.   TRY_TO_MATCH
  273.     (
  274.      (buf, "Board:      %c%c %c%c %c%c", &r1, &s1, &r2, &s2, &r3, &s3), 6,
  275.      {[pokerTable publicCardNumber:0 didShowCard:[self cardFromRankChar:r1 suitChar:s1]];
  276.       [pokerTable publicCardNumber:1 didShowCard:[self cardFromRankChar:r2 suitChar:s2]];
  277.       [pokerTable publicCardNumber:2 didShowCard:[self cardFromRankChar:r3 suitChar:s3]];});
  278.  
  279.   TRY_TO_MATCH
  280.     (
  281.      (buf, "%s bets $%d.  Pot is now $%d.", player, &amount, &pot), 3,
  282.      [pokerTable player:player bets:amount potNow:pot allIn:NO]);
  283.  
  284.   TRY_TO_MATCH
  285.     (
  286.      (buf, "%s bets $%d and is all in.  Pot is now $%d.", player, &amount, &pot), 3,
  287.      [pokerTable player:player bets:amount potNow:pot allIn:YES]);
  288.  
  289.   TRY_TO_MATCH
  290.     (
  291.      (buf, "%s is back from vacation%c", player, &bang), 2,
  292.      [pokerTable playerBackFromVacation:player]);
  293.  
  294.   TRY_TO_MATCH
  295.     (
  296.      (buf, "%s wins $%d.", player, &amount), 2,
  297.      [pokerTable player:player wins:amount withHand:NULL]);
  298.  
  299.   TRY_TO_MATCH
  300.     (
  301.      (buf, "High: %s wins $%d with %s.", player, &amount, hand_string), 3,
  302.      [pokerTable player:player wins:amount withHand:hand_string]);
  303.  
  304.   TRY_TO_MATCH
  305.     (
  306.      (buf, "Players' hands%c", &colon), 1,
  307.      [pokerTable aboutToShowHands]);
  308.  
  309.   TRY_TO_MATCH
  310.     (
  311.      (buf, "Your hole cards are: %c%c %c%c", &r1, &s1, &r2, &s2), 4,
  312.      [pokerTable userGotFirstHoleCard:[self cardFromRankChar:r1 suitChar:s1]
  313.                   secondCard:[self cardFromRankChar:r2 suitChar:s2]]);
  314.  
  315.   TRY_TO_MATCH
  316.     (
  317.      (buf, "%s : %c%c %c%c", player, &r1, &s1, &r2, &s2), 5,
  318.      {Player *p;
  319.       p = [pokerTable findPlayerWithName:player];
  320.       [[p holeHand] setFirstHoleCard:[self cardFromRankChar:r1 suitChar:s1]];
  321.       [[p holeHand] setSecondHoleCard:[self cardFromRankChar:r2 suitChar:s2]];});
  322.  
  323.   TRY_TO_MATCH
  324.     (
  325.      (buf, "%s raises $%d.  Pot is now $%d.", player, &amount, &pot), 3,
  326.      [pokerTable player:player raises:amount potNow:pot allIn:NO]);
  327.  
  328.   TRY_TO_MATCH
  329.     (
  330.      (buf, "%s raises $%d and is all in.  Pot is now $%d.", player, &amount, &pot), 3,
  331.      [pokerTable player:player raises:amount potNow:pot allIn:YES]);
  332.  
  333.   TRY_TO_MATCH
  334.     (
  335.      (buf, "%s is busted%c", player, &bang), 2,
  336.      [pokerTable playerBusted:player]);
  337.  
  338.   TRY_TO_MATCH
  339.     (
  340.      (buf, "%s has quit%c", player, &dot), 2,
  341.      [pokerTable playerQuit:player]);
  342.  
  343.   if (buf[0] == ' ' || buf[0] == 'V' || buf[0] == 'B')
  344.     {
  345.       char c1, c2;
  346.  
  347.       if (sscanf (buf, "%c%c%s %d", &c1, &c2, player, &amount) == 4)
  348.     {
  349.           [self addPlayerHelper:player cash:amount char1:c1 char2:c2];
  350.           buf = strchr (buf+2, ' ');
  351.       while (*buf == ' ')
  352.         ++buf;
  353.       buf = strchr (buf, ' ');
  354. #if 0
  355.       while (strncmp (buf, "   ", 3) == 0 || (*buf == ' ' && buf[1] != ' '))
  356.         ++buf;
  357. #else
  358.       buf += 3;
  359. #endif
  360.           if (sscanf (buf, "%c%c%s %d", &c1, &c2, player, &amount) == 4)
  361.             {
  362.               [self addPlayerHelper:player cash:amount char1:c1 char2:c2];
  363.               buf = strchr (buf+2, ' ');
  364.               while (*buf == ' ')
  365.                 ++buf;
  366.               buf = strchr (buf, ' ');
  367. #if 0
  368.               while (strncmp (buf, "   ", 3) == 0 || (*buf == ' ' && buf[1] != ' '))
  369.                 ++buf;
  370. #else
  371.           buf += 3;
  372. #endif
  373.               if (sscanf (buf, "%c%c%s %d", &c1, &c2, player, &amount) == 4)
  374.                   [self addPlayerHelper:player cash:amount char1:c1 char2:c2];
  375.         }
  376.         }
  377.     }
  378.  
  379.   retval = FALSE;
  380.  SUCCESS:
  381.   return retval;
  382. }
  383.  
  384.  
  385. - (void) gotSomeData:(NSNotification *)note
  386. {
  387.   NSData *data;
  388.   const char *start_bytes, *stop_bytes;
  389.   int length;
  390.  
  391. #warning THIS CODE ASSUMES LINE WONT SPLIT ACROSS DATA
  392.  
  393.   data = [[note userInfo] objectForKey:NSFileHandleNotificationDataItem];
  394.   start_bytes = [data bytes];
  395.   length = [data length];
  396.   stop_bytes = start_bytes;
  397.   while (length > 0)
  398.     {
  399.       while (length > 0 && *stop_bytes != '\n')
  400.     {
  401.       ++stop_bytes;
  402.       --length;
  403.     }
  404.       if (stop_bytes > start_bytes)
  405.     {
  406.       NSData *new_data;
  407.  
  408.       new_data = [NSData dataWithBytes:start_bytes length:stop_bytes - start_bytes];
  409.       [pokerTable setStatusString:[[[NSString alloc]initWithData:new_data encoding:[NSString defaultCStringEncoding]]autorelease]];
  410.       [self parseLine:new_data];
  411.     }
  412.       start_bytes = stop_bytes + 1;
  413.       stop_bytes = start_bytes;
  414.       --length;
  415.     }
  416.   [[from_irc fileHandleForReading] readInBackgroundAndNotify];
  417. }
  418.  
  419. - (void)makeIRCConnection:(PokerTable *)table
  420. {
  421.     NSMutableArray *args = [NSMutableArray array];
  422.     pokerTable = table;
  423.     aTask = [[NSTask alloc] init];
  424.     to_irc = [NSPipe pipe];
  425.     from_irc = [NSPipe pipe];
  426. #if 1
  427.     [args addObject:@"-d"];
  428.     [args addObject:@"deadhead"];
  429.     [args addObject:@"irc.poker.net"];
  430.     [aTask setLaunchPath:IRC_EXECUTABLE];
  431. #else
  432.     [args addObject:@"/Local/Users/machack/ctm/poker/tbot2/typescript_FIRST_OFFICIAL_SCORE"];
  433.     [aTask setLaunchPath:@"/bin/cat"];
  434. #endif
  435.     [aTask setArguments:args];
  436.     [aTask setStandardInput:to_irc];
  437.     [aTask setStandardOutput:from_irc];
  438.     [[NSNotificationCenter defaultCenter]
  439.      addObserver:self
  440.      selector:@selector(gotSomeData:)
  441.      name:NSFileHandleReadCompletionNotification object:nil];
  442.  
  443.     [[from_irc fileHandleForReading] readInBackgroundAndNotify];
  444.     [pokerTable newPokerTable];
  445.     [aTask launch];
  446.  
  447. }
  448. @end
  449.